#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include "LockGuard.hpp"
using namespace std;

#define NUM 4

pthread_mutex_t lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;

// 用多线程模拟一轮抢票
int tickets = 1000;

class threadData{
public:
    threadData(int number/*, pthread_mutex_t *mutex*/)
    :_threadname("thread-"+to_string(number))
    /*,lock(mutex)*/
    {}
public:
    string _threadname;
    //pthread_mutex_t *lock;
};


// void *GetTicket(void *args){
//     threadData *td = static_cast<threadData *>(args);
//     while(true){
//         // 加锁
//         //pthread_mutex_lock(td->lock);
//         if (tickets > 0)
//         {
//             usleep(1000);
//             cout << "who=" << td->_threadname << ", get a ticket: " << tickets << endl;
//             tickets--;
//             // 解锁
//             //pthread_mutex_unlock(td->lock);
//         }
//         else{
//             //pthread_mutex_unlock(td->lock);
//             break;
//         }

//         usleep(10); // 模拟实现多线程抢到票之后的后续动作
//     }
//     cout << td->_threadname << " .... quit!" << endl;
//     return nullptr;
// }

// RAII锁的使用
void *GetTicket(void *args){
    threadData *td = static_cast<threadData *>(args);
    while(true){
        // 花括号区间就是临时区
        {
            // 利用临时对象的生命周期，创建时自动调用构造函数加锁
            LockGuard mutex(&lock);
            if (tickets > 0){
                usleep(1000);
                cout << "who=" << td->_threadname << ", get a ticket: " << tickets << endl;
                tickets--;
            }
            else{
                break;
            }
            // 区间结束时，自动调用析构函数释放锁
        }

        usleep(10); // 模拟实现多线程抢到票之后的后续动作
    }
    cout << td->_threadname << " .... quit!" << endl;
    return nullptr;
}

int main(){
    // // 创建一个互斥锁
    // pthread_mutex_t lock;
    // // 初始化
    // pthread_mutex_init(&lock, nullptr);

    vector<pthread_t> tids;
    vector<threadData *> thread_datas;
    for (int i = 1; i <= NUM;i++){
        pthread_t tid;
        threadData *td = new threadData(i/*, &lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, GetTicket, td);
        tids.push_back(tid);
    }

    for(auto tid : tids){
        pthread_join(tid, nullptr);
    }
    for(auto td : thread_datas){
        delete td;
    }

    // // 销毁互斥锁
    // pthread_mutex_destroy(&lock);

    return 0;
}